package org.gdpu.Service.Impl;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.gdpu.Service.DormitoryService;
import org.gdpu.Service.MajorService;
import org.gdpu.Service.StudentService;
import org.gdpu.base.DaoSupport;
import org.gdpu.model.*;
import org.gdpu.util.ChangeTime;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.persistence.Query;
import java.util.*;

/**
 * Created by HEWI2 on 2/17/14.
 */

@Service
@Transactional
public class StudentServiceImpl extends DaoSupport<Student> implements StudentService {

    private final static Logger logger = LogManager.getLogger(StudentServiceImpl.class);
    private DormitoryService dormitoryService;
    private MajorService majorService;

    @Override
    public void changeMonitor(String stuId) {
        Student student = this.findStudent("studentId", Integer.valueOf(stuId)).get(0);
        student.setMonitor(Monitor.MONITOR);
        this.update(student);
        List<Student> students = this.findStudent("dormitory", student.getDormitory());
        for (Student s : students) {
            if (s.getStudentId() != student.getStudentId()) {
                s.setMonitor(Monitor.NOT_MONITOR);
                this.update(s);
            }
        }
    }

    @Override
    public List<Student> findStudent(String key, Object value) {
        Map<String, Object> params = new HashMap<String, Object>();
        if ("dormitory".equals(key)) {
            params.put("dormitory", value);
        } else if ("major".equals(key)) {
            params.put("major", majorService.findByName(value.toString()));
        } else if ("dormitory+campus".equals(key)) {
            params.put("dormitory", dormitoryService.findById(value.toString().substring(0, 4), value.toString().substring(4)));
        } else if ("noDormitory".equals(key)) {
            Query query = em.createQuery("from Student s where s.dormitory IS NULL ");
            return query.getResultList();
        } else if ("building".equals(key)) {
            Query query = em.createQuery("from Dormitory d where d.dormitoryId like ?1 and d.campus.campusName=?2 order by d.dormitoryId");
            query.setParameter(1, value.toString().substring(0, 1) + "%");
            query.setParameter(2, value.toString().substring(1));
            List<Dormitory> dys = query.getResultList();
            List<Student> sts = new ArrayList<Student>();
            for (Dormitory dormitory : dys) {
                params.put("dormitory", dormitory);
                sts.addAll((List<Student>) this.findByFields(Student.class, params));
            }
            return sts;
        } else if ("college".equals(key)) {
            List<Major> mrs = new ArrayList<Major>();
            List<Student> sts = new ArrayList<Student>();
            mrs = majorService.findByCollege(String.valueOf(value));
            for (Major major : mrs) {
                params.put("major", major);
                sts.addAll((List<Student>) this.findByFields(Student.class, params));
            }
            return sts;
        } else if ("relocate".equals(key)) {
            Query query = em.createQuery("from Student s where s.leaveDate=?1 and s.dormitory.id in (SELECT d.id from Dormitory d where d.campus.campusName =?2)");
            query.setParameter(1, ChangeTime.parseShortDate(Calendar.getInstance().get(Calendar.YEAR) + "-6-30"));
            query.setParameter(2, String.valueOf(value));
            return query.getResultList();
        } else
            params.put(key, value);
        return (List<Student>) this.findByFields(Student.class, params);
    }

    @Override
    public boolean checkMonitor(Dormitory dormitory) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("dormitory", dormitory);
        params.put("monitor", Monitor.MONITOR);
        return this.findSpecialObject(Student.class, params) == null ? false : true;
    }

    //TODO:每年9月1日~9月5日可以修改舍长
    @Override
    public boolean isShowChangeMonitor(String group, String dormitoryId) {
        Dormitory dormitory = new Dormitory();
        if ("学生宿舍".equals(group)) {
            dormitory = this.find(Dormitory.class, Integer.valueOf(dormitoryId));
        }
        if ("管理员".equals(group)) {
            return true;
        } else if (Calendar.getInstance().get(Calendar.MONTH) + 1 == 9 && Calendar.getInstance().get(Calendar.DATE) < 5) {
            return true;
        } else if (!this.checkMonitor(dormitory)) {
            return true;
        } else
            return false;
    }

    @Override
    public String checkIn(Student student) {
        Query query = em.createQuery("from Dormitory o WHERE o.id in (SELECT s.dormitory.id from Student s WHERE s.major = ?1 and s.sex= ?2) and o.dormitoryState=?3");
        query.setParameter(1, student.getMajor());
        query.setParameter(2, student.getSex());
        query.setParameter(3, DormitoryState.NOT_FULL);
        List<Dormitory> dormitories = query.getResultList();
        if (dormitories.size() != 0) {
            student.setDormitory(dormitories.get(0));
            this.update(student);
            Dormitory d = dormitories.get(0);
            d.setNum(d.getNum() + 1);
            if (d.getNum() == 4)
                d.setDormitoryState(DormitoryState.FULL);
            else
                d.setDormitoryState(DormitoryState.NOT_FULL);
            this.update(d);
        } else {
            query = em.createQuery("from Dormitory d WHERE d.dormitoryState= ?1 and d.sex= ?2 and d.campus in " +
                    "(SELECT c.campus from College c where c.id = (SELECT m.college.id " +
                    "from Major m WHERE m.majorId = ?3))");
            query.setParameter(1, DormitoryState.EMPTY);
            query.setParameter(2, student.getSex());
            query.setParameter(3, student.getMajor().getMajorId());
            dormitories = query.getResultList();
            if (dormitories.size() == 0)
                return "";
            else {
                student.setDormitory(dormitories.get(0));
                this.update(student);
                Dormitory d = dormitories.get(0);
                d.setNum(d.getNum() + 1);
                if (d.getNum() == 4)
                    d.setDormitoryState(DormitoryState.FULL);
                else
                    d.setDormitoryState(DormitoryState.NOT_FULL);
                this.update(d);
            }
        }
        return student.getDormitory().getDormitoryId();
    }

    @Override
    public List<Student> findStudents(String dormitoryId) {
        Dormitory dormitory = dormitoryService.find(Dormitory.class, Integer.valueOf(dormitoryId));
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("dormitory", dormitory);
        return (List<Student>) this.findByFields(Student.class, params);
    }

    @Override
    public List<Student> findStudents(String dormitoryId, String campusName, String sex) {
        if (sex.equals("MALE"))
            sex = "男生";
        else
            sex = "女生";
        Dormitory dormitory = dormitoryService.findById(dormitoryId, campusName);
        if (!dormitory.getSex().toString().equals(sex)) {
            Student student = new Student();
            student.setStudentId(1111111);
            List<Student> students = new ArrayList<Student>();
            students.add(student);
            return students;
        }

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("dormitory", dormitory);
        return (List<Student>) this.findByFields(Student.class, params);
    }

    @Override
    public void setDormitory(int[] stuIds, String dormitoryId) {
        Dormitory dormitory = dormitoryService.find(Dormitory.class, Integer.parseInt(dormitoryId));
        for (int i : stuIds) {
            Student student = this.find(Student.class, i);
            student.setDormitory(dormitory);
            this.update(student);
            dormitory.setNum(dormitory.getNum() + 1);
            dormitory.setSex(student.getSex());
            if (dormitory.getNum() == 4)
                dormitory.setDormitoryState(DormitoryState.FULL);
            else
                dormitory.setDormitoryState(DormitoryState.NOT_FULL);
            this.update(dormitory);
        }
    }

    @Override
    public boolean changeDormitory(Student apply, Student exchange) {
        Dormitory applyDormitory = apply.getDormitory();
        apply.setDormitory(exchange.getDormitory());
        exchange.setDormitory(applyDormitory);
        try {
            this.update(apply);
            this.update(exchange);
        } catch (Exception e) {
            logger.error(e);
            return false;
        }
        return true;
    }

    @Resource(name = "dormitoryServiceImpl")
    public void setDormitoryService(DormitoryService dormitoryService) {
        this.dormitoryService = dormitoryService;
    }

    @Resource(name = "majorServiceImpl")
    public void setMajorService(MajorService majorService) {
        this.majorService = majorService;
    }
}
